home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 16
/
Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso
/
Aminet
/
misc
/
emu
/
QDOS2.lha
/
QLsource
/
src
/
L_QDOS.c
next >
Wrap
C/C++ Source or Header
|
1996-02-06
|
10KB
|
538 lines
;/*
A68k sub.asm
dcc -o L_QDOS L_QDOS.c -l hardware SUB.o
quit
*/
/* L_QDOS loads and runs QDOS */
#include <exec/exec.h>
#include <exec/libraries.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <workbench/workbench.h>
#include <stdio.h>
#include <hardware/cia.h>
#define MAXROMS 16
extern struct ExecBase *SysBase;
extern __far struct CIA ciaa, ciab;
typedef struct List LIST;
typedef struct Node NODE;
typedef struct MemHeader MEMHEADER;
typedef struct MemChunk MEMCHUNK;
extern int sub(),dummy();
extern int subtoclear();
long ql_lomem,ql_himem,ql_ssp,ql_var,rom_lomem;
int sflag,mflag,cflag,ccount,rflag,rcount,dflag;
long qldate;
struct
{
long day;
long min;
long tick;
} date;
struct rominfo
{
char *name;
VOID *fp;
long len;
long rlen;
};
struct memrange
{
long lomem;
long himem;
};
struct memrange *toclear;
struct rominfo rom[MAXROMS];
typedef struct CommandLineInterface CLI;
typedef struct Process PROCESS;
CLI *cli;
PROCESS *proc;
extern int _start_();
extern int _realstart_();
extern long _Detached_, /* are we detached? */
_WorkBench_, /* are we on the WB? */
_CLI_, /* are we on the CLI? */
_Process_; /* are we a process? */
#if 1
/* how to change the default console (if it's used) */
char _DefaultConsole[] =
"CON:0/12/320/72/L_QDOS 2.03, loading QDOS...";
#endif
char VERSTAG[] = "\0$VER: L_QDOS 2.03";
shutdown(s) char *s;
{
printf("%ls\n",s);
if(_WorkBench_ || _Detached_)
{
Delay(500);
}
exit(0);
}
usage()
{
shutdown("L_QDOS v2.03\n\n"
"usage:\tL_QDOS [-r]\n"
"\t [-q<QDOS rom>]\n"
"\t [-p<MAIN rom>]\n"
"\t [-m<lomem><+len|-himem>]\n"
"\t [<OTHER roms>...]\n");
}
warning(s) char *s;
{
printf("%ls\n",s);
}
char *
getnum(p,np) char *p; long *np;
{ long n,h;
char c;
c=*p++;
n=0;
if(c!='$')
{
while(isdigit(c))
{
h=c-48;
n=n*10+h;
c=*p++;
}
}
else
{
c=*p++;
while(isxdigit(c))
{
h=(c<58?c-48:(c<96?c-55:c-87));
n=n*16+h;
c=*p++;
}
}
*np=n;
return --p;
}
doflags(p) char *p;
{
long num;
while(*p!=0)
{ switch(toupper(*p++))
{
case 'D':
dflag=1;
break;
case 'R':
rflag=1;
break;
case 'Q':
rom[0].name=p;
while (*p!=0)
p++;
break;
case 'P':
rom[1].name=p;
while (*p!=0)
p++;
break;
case 'M':
while(*p!=0)
{ p=getnum(p,&num);
switch(*p)
{
case '+':
mflag=1;
ql_var=num;
break;
case '-':
mflag=2;
ql_var=num;
break;
case 0:
switch(mflag)
{
case 1:
ql_himem=ql_var+num;
break;
case 2:
ql_himem=num;
break;
default:
usage();
}
break;
default:
usage();
}
if(*p!=0)
p++;
}
break;
default:
usage();
}
}
}
int
findrom(rom) struct rominfo *rom;
{
long len;
VOID *f;
char temp[80];
f = fopen(rom->name,"r");
if(f == 0)
{ strcpy(temp,rom->name);
strcat(temp," not available");
warning(temp);
len=0;
}
else
{ fseek(f,0,2);
len=ftell(f);
fseek(f,0,0);
}
rom->fp = f;
rom->len=len;
len+=255;
len&=-256;
rom->rlen=len;
return len;
}
main(argc,argv)
int argc;
char **argv;
{
int i,j,n;
long olddir;
long rom_tot,rom_len,len,rom_dst,sub_len,sub_dst;
char *p,*qp,*cp,**av;
MEMHEADER *mh;
long mh_lower, mh_upper;
_DetachFromCLI(); /* Does just that. (Or nothing if */
/* run from the WorkBench). */
_RunOnWorkBench(); /* Indicates this program should */
/* continue and will run properly */
/* if started from the WorkBench. */
/* Well, you say it will. */
_ToolTypeArgs(); /* Means move tooltype array from */
/* .info file to argc,argv. */
_OpenDefaultConsole(); /* Need this to use printf's etc */
/* when starting from WorkBench */
/* or if you've detached. */
/* (You won't need it if you're */
/* only using intuition stuff). */
/* Does nothing if you're running */
/* on the CLI/Shell. */
toclear=(struct memrange *)subtoclear;
mflag=sflag=cflag=ccount=rflag=dflag=0;
rcount=2;
ql_lomem=rom_lomem=0;
ql_himem=0x10000000;
ql_ssp=0x28480;
ql_var=0x28000;
for(i=1;i<argc;i++)
{
/* printf("arg %ld = %ls\n",i,argv[i]); */
if(argv[i][0]=='?')
usage();
if(argv[i][0]=='-')
doflags(argv[i]+1);
else
{
if(rcount<MAXROMS)
{ rom[rcount].name=argv[i];
rcount++;
}
else
shutdown("too many roms");
}
}
if(dflag!=0)
warning("...now in debug mode");
if(dflag!=0)
printf("to clear structure=$%lx $%lx\n\n",(long)toclear,(long)subtoclear);
ccount=0;
for (mh = (MEMHEADER *)GetHead((LIST *)&SysBase->MemList);
mh != 0;
mh = (MEMHEADER *)GetSucc((NODE *)mh))
{
mh_lower=mh->mh_Lower;
mh_upper=mh->mh_Upper;
if (((long)mh+sizeof(MEMHEADER))=mh_lower)
mh_lower=(long)mh;
if (ccount!=0)
for (i=0;i<ccount;i++)
if (mh_lower<toclear[i].lomem)
{
n=mh_lower;mh_lower=toclear[i].lomem;toclear[i].lomem=n;
n=mh_upper;mh_upper=toclear[i].himem;toclear[i].himem=n;
}
toclear[ccount].lomem=mh_lower;
toclear[ccount].himem=mh_upper;
ccount++;
}
i=0;
while ((i<ccount)&(ql_var>toclear[i].himem))
i++;
if (i<ccount)
if (ql_var<toclear[i].lomem)
ql_var=toclear[i].lomem;
i=ccount-1;
while ((i>=0)&(ql_himem<toclear[i].lomem))
i--;
if (i>=0)
if (ql_himem>toclear[i].himem)
ql_himem=toclear[i].himem;
if (ql_himem>0x1000000)
if (ql_var<toclear[ccount-1].lomem)
ql_var=toclear[ccount-1].lomem;
if(dflag!=0)
{
for (i=0;i<ccount;i++)
printf("$%08lX $%08lX \n",toclear[i].lomem,toclear[i].himem);
}
if(rom[0].name==0)
rom[0].name="QLboot:ROMs/SYS_cde";
if(rom[1].name==0)
rom[1].name="QLboot:ROMs/MAIN_cde";
rom_tot=0;
for(i=0;i==0 || i<rcount;i++)
{ len=findrom(&rom[i]);
if((len==0)&&(i<2))
shutdown("sorry but I can't load QDOS");
if(dflag!=0)
printf("%ls\n",rom[i].name);
rom_tot+=len;
}
if(dflag!=0)
printf("total space req=$%lx/%ld\n",rom_tot,rom_tot);
if(rom_tot!=0)
{
p = (char *)malloc(rom_tot);
if(p==0)
shutdown("no memory");
qp=p;
for(i=0;i<rcount;i++)
{ if(rom[i].len!=0)
{ fread(p,rom[i].len,1,rom[i].fp);
p+=rom[i].rlen;
}
}
}
rom_len=rom_tot-rom[0].rlen-rom[1].rlen;
if(dflag!=0)
{ printf("QDOS and ROMS source=$%lx\n",qp);
printf("QDOS len=$%lx\n",rom[0].rlen);
printf("MAIN len=$%lx\n",rom[1].rlen);
printf("ROMs len=$%lx\n\n",rom_len);
}
DateStamp(&date);
qldate=date.day+365*17+4;
qldate=qldate*(24*60*60/8);
qldate<<=3;
qldate+=(date.min*60);
qldate+=(date.tick/50);
if(dflag!=0)
{ printf("days=%ld mins=%ld ticks=%ld\n",date.day,date.min,date.tick);
printf("qldate=$%08lx\n",qldate);
}
ql_var=(ql_var+0x7FFF)&(-0x8000);
ql_himem=ql_himem&(-0x200);
rom_dst=(ql_himem-rom_len)&(-0x200);
sub_len=(long)dummy-(long)sub;
sub_dst=((ql_himem-rom_tot)&(-0x200))-sub_len;
ql_himem=rom_dst;
if(rflag!=0)
if(ql_himem>0x200000)
ql_himem=ql_himem-rom[0].rlen+0x600;
if(dflag!=0)
printf("rom_dst=$%lx\n",rom_dst);
if(ql_var<0x28000)
ql_var=0x28000;
ql_ssp=ql_var+0x480;
ql_lomem=ql_ssp;
if(dflag!=0)
printf("lomem=$%lx himem=$%lx\n\n",ql_lomem,ql_himem);
if(ql_lomem>=ql_himem)
shutdown("bad value for memory range\n...might be out of memory\n ");
check_dst:
if(((long)qp <= sub_dst) && ((long)qp + rom_tot > sub_dst))
sub_dst=qp-sub_len;
if(((long)sub<=sub_dst)&&((long)sub+sub_len>sub_dst))
{ sub_dst=(long)sub-sub_len;
goto check_dst;
}
if(dflag!=0)
printf("sub src=$%lx sub dst=$%lx sub len=$%lx\n\n"
,(long)sub,sub_dst,sub_len);
i=0;
while(i<ccount)
{
if(toclear[i].lomem<rom[0].rlen)
{ if(toclear[i].himem>rom[0].rlen)
toclear[i].lomem=rom[0].rlen;
else
goto removerange;
}
if(toclear[i].lomem<0x1c000)
{ if(toclear[i].himem>0x1c000)
{ if(toclear[i].himem>(0x1c000+rom[1].rlen))
{ if(ccount<8)
{ toclear[ccount].lomem=0x1c000+rom[1].rlen;
toclear[ccount].himem=toclear[i].himem;
ccount++;
}
else
shutdown("range too complex");
}
toclear[i].himem=0x1c000;
}
}
if(toclear[i].lomem<sub_dst)
{ if(toclear[i].himem>sub_dst)
{ if(toclear[i].himem>(sub_dst+sub_len))
{ if(ccount<8)
{ toclear[ccount].lomem=sub_dst+sub_len;
toclear[ccount].himem=toclear[i].himem;
ccount++;
}
else
shutdown("range too complex");
}
toclear[i].himem=sub_dst;
}
}
if(toclear[i].lomem<rom_dst)
{ if(toclear[i].himem>rom_dst)
{ if(toclear[i].himem>(rom_dst+rom_len))
{ if(ccount<8)
{ toclear[ccount].lomem=rom_dst+rom_len;
toclear[ccount].himem=toclear[i].himem;
ccount++;
}
else
shutdown("range too complex");
}
toclear[i].himem=rom_dst;
}
}
if(toclear[i].lomem<ql_himem)
{ if(toclear[i].himem>ql_himem)
toclear[i].himem=ql_himem;
}
else
goto removerange;
if(toclear[i].lomem==toclear[i].himem)
goto removerange;
i++;
goto endwhile;
removerange:
ccount--;
toclear[i].lomem=toclear[ccount].lomem;
toclear[i].himem=toclear[ccount].himem;
endwhile:
}
toclear[ccount].lomem=0;
toclear[ccount].himem=0;
if(dflag!=0)
{ i=0;
while(i<ccount)
{ printf("range: lomem=$%lx himem=%lx\n"
,toclear[i].lomem,toclear[i].himem);
i++;
}
}
if(dflag!=0)
{ printf("vars=$%lx ssp=$%lx\n\n",ql_var,ql_ssp);
shutdown("quitting L_QDOS...\n");
}
Forbid();
Disable();
OwnBlitter();
while(WaitBlit());
if(((struct Library *)SysBase)->lib_Version>=37)
CacheControl(0,CACRF_EnableI|CACRF_EnableD|CACRF_IBE|CACRF_DBE);
/* deselect all drives */
ciab.ciaprb|=CIAF_DSKSEL0|CIAF_DSKSEL1|CIAF_DSKSEL2|CIAF_DSKSEL3;
/* motor signal (off) */
ciab.ciaprb|=CIAF_DSKMOTOR;
/* select all drives (thus, switch them off) */
ciab.ciaprb&=~(CIAF_DSKSEL0|CIAF_DSKSEL1|CIAF_DSKSEL2|CIAF_DSKSEL3);
/* deselect drives again (well, why not?) */
ciab.ciaprb|=CIAF_DSKSEL0|CIAF_DSKSEL1|CIAF_DSKSEL2|CIAF_DSKSEL3;
sub(sub_dst,ql_lomem,ql_himem,rom_dst,qp,
rom[0].rlen,rom_len,rom[1].rlen,ql_ssp,qldate);
}